/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Sindarin.ScriptParser;

import java.util.Stack;
import java.util.Vector;
import java.io.File;
import java.io.FileReader;
import java.io.LineNumberReader;
import java.io.StringReader;
import java.util.StringTokenizer;
import java.io.FileNotFoundException;
import java.io.IOException;
import Sindarin.Common.CodeFileClass;
import Sindarin.Common.FileHeader;
import Sindarin.Common.Instruction;
import Sindarin.Common.Instruction.Opcode;
import Sindarin.Common.Symbol;
import Sindarin.Common.SymbolTable;

/**
 *
 * @author user
 */
public abstract class AbstractParser {

    //static final private int RETR_PULSACION = 5;
    //static final private int RETR_DRAG0 = 1500; // retrazo entre mousepress y say en el drag en milisegundos
    //static final private int RETR_DRAG1 = 1000; // retrazo entre mousepress y say en el drag
    static final protected int RETR_PULSACION = 3;
    static final protected int RETR_DRAG0 = 1300; // retrazo entre mousepress y say en el drag en milisegundos
    static final protected int RETR_DRAG1 = 800; // retrazo entre mousepress y say en el drag
    static final public String BOTON1 = "left";
    static final public String BOTON2 = "right";
    static final public int VERSION = 0;
    static final public int REVISION = 33;
    static final public String VERSION_STRING = VERSION + "." + REVISION;
    static public boolean debug = false;
    public SymbolTable symbolTable;
    public Stack instNoRes = new Stack();
    public Vector instVector;
    public Stack etq = new Stack();
    protected Stack breakEtq = new Stack();

    protected void resolEtq() {
        while (!instNoRes.isEmpty()) {
            Instruction act = (Instruction) instNoRes.pop();
            act.operator = (Integer) ((Symbol) act.operator).value;
        }
    }

    public void setSymbolTable(SymbolTable nSymbol) {
        symbolTable = nSymbol;
    }

    public void setInstVector(Vector nInstVector) {
        instVector = nInstVector;
    }

    public Vector getInstVector() {
        return instVector;
    }

    public SymbolTable getSymbolTable() {
        return symbolTable;
    }

    public void inic() {
        setSymbolTable(new SymbolTable());
        setInstVector(new Vector());
    }

    public void newInst(Instruction nInst) {
        instVector.add(nInst);
    }

    public static void main(String args[]) throws ParseException {
        ScriptParser parser = new ScriptParser(System.in);
        parser.inic();
        parser.begin();
    }

    public void genError(int linea, String mensj) {
        System.err.println("Linea " + linea + ": ERROR, " + mensj);
    }

    public void genStore(Token tok, int type) {
        Symbol tmpSimb = symbolTable.find(tok.image);
        if (tmpSimb == null) {
            symbolTable.newSymbol(tok, ScriptParser.UNDEF);
            genError(tok.beginLine, "Variable " + tok.image + " no existe, no esta definida");
        } else {
            if (tmpSimb.type != type) {
                genError(tok.beginLine, "Variable " + tok.image + " es de tipo "
                        + ScriptParserConstants.tokenImage[tmpSimb.type]
                        + " y se a intentado asignarla a un tipo "
                        + ScriptParserConstants.tokenImage[type]);
            }
            if (tmpSimb.token.beginLine > 0) {
                newInst(new Instruction(Opcode.STORE, tok.image));
            } else {
                genError(tok.beginLine, "Variable " + tok.image + " es una variable de Sindarin, estas no pueden ser modificadas");
            }
        }
    }

    public void defVarSystem(String name, int type, Object value) {
        Token tmp = new Token();            // Genera variable
        tmp.image = name;
        tmp.kind = type;
        tmp.beginLine = 0;
        symbolTable.newSymbol(new Symbol(value, type, tmp));
    }

    public StringReader ReaderFile(String path) throws FileNotFoundException, IOException {
        StringReader stringIn = null;
        String nScript = "";
        StringTokenizer str = new StringTokenizer(path, "\"");
        File inputFile = new File(str.nextToken());
        LineNumberReader in = new LineNumberReader(new FileReader(inputFile));
        String code = in.readLine();
        nScript = code;
        code = in.readLine();
        do {
            if (code != null) {
                nScript += "\n" + code;
                code = in.readLine();
            }
        } while (code != null);
        stringIn = new StringReader(nScript);
        return stringIn;
    }

    public void saveStateFile(File f) throws Exception {
        saveStateFile(f, new FileHeader());
    }

    public void saveStateFile(File f, FileHeader header) throws Exception {
        saveStateFile(f, header, null);
    }

    public void saveStateFile(File f, FileHeader header, String pass) throws Exception {
        if ((header.cypher) && ((pass == null) || (pass.equals("")))) {
            pass = CodeFileClass.getPassDialog();
        }

        CodeFileClass.saveFile(f, pass, header, instVector, symbolTable);
    }

    @Override
    public String toString() {
        int i = 0;
        String res = "Instruction: \n";
        for (Instruction inst : (Vector<Instruction>) getInstVector()) {
            res += "PC: " + i + " " + inst + "\n";
            i++;
        }
        return res;
    }
}
